import { app } from '../utilities/app'

function createErrorClass (name, SuperClass, defaultMessage, code) {
  function RequestError (message) {
    this.message = message || defaultMessage
    this.stack = new Error(message).stack // 错误堆栈 即告诉错误的具体位置
  }
  RequestError.prototype = Object.create(SuperClass.prototype)
  RequestError.prototype.constructor = RequestError
  RequestError.prototype.name = name
  if (code) {
    RequestError.prototype.code = code
  }
  return RequestError
}

export const RequestError = createErrorClass(
  'RequestError',
  Error,
  '请求失败'
)

export const ResponseError = createErrorClass(
  'ResponseError',
  RequestError,
  '请求失败'
)

export const ServerError = createErrorClass(
  'ServerError',
  ResponseError,
  '服务器异常，请联系管理员或稍后再试',
  '1111'
)

export const InvalidParamsError = createErrorClass(
  'InvalidParamsError',
  ResponseError,
  '请求参数错误，请检查你提交的数据',
  '3333'
)

export const AdminError = createErrorClass(
  'AdminError',
  ResponseError,
  '请求失败'
)

export const TokenInvalidError = createErrorClass(
  'TokenInvalidError',
  AdminError,
  '请重新登录！',
  '5000'
)

export const PermissionDeniedError = createErrorClass(
  'PermissionDeniedError',
  AdminError,
  '对不起，你没有权限',
  '5001'
)
export const PermissionNot = createErrorClass(
  'PermissionNot',
  AdminError,
  '请选择权限',
  '5011'
)
export const RoleNameDuplicatedError = createErrorClass(
  'RoleNameDuplicatedError',
  AdminError,
  '角色名已被占用',
  '5002'
)

export const RoleInUseError = createErrorClass(
  'RoleInUseError',
  AdminError,
  '该角色正在被使用，无法删除',
  '5003'
)

export const AdminLockedError = createErrorClass(
  'AdminLockedError',
  AdminError,
  '帐号已被锁定',
  '5004'
)

export const ModuleNameDuplicatedError = createErrorClass(
  'ModuleNameDuplicatedError',
  AdminError,
  '模块名已被占用',
  '5005'
)

export const LoginError = createErrorClass(
  'LoginError',
  AdminError,
  '用户名或密码错误',
  '5006'
)

export const AccountNameDuplicatedError = createErrorClass(
  'AccountNameDuplicatedError',
  AdminError,
  '帐号已被占用',
  '5007'
)

export const SystemError = createErrorClass(
  'SystemError',
  ResponseError,
  '请求失败'
)

export const SignatureError = createErrorClass(
  'ResponseError',
  SystemError,
  process.env.NODE_ENV === 'production'
      ? '请求失败，请联系管理员'
      : '数据签名失败',
  '6001'
)

export const WechatError = createErrorClass(
  'WechatError',
  ResponseError,
  '请求失败'
)

export const WechatRequestError = createErrorClass(
  'WechatRequestError',
  WechatError,
  '请求微信服务失败，请联系管理员或稍后再试',
  '7001'
)

export const WechatAccountDuplicatedError = createErrorClass(
  'WechatAccountDuplicatedError',
  WechatError,
  '该微信号已被绑定',
  '7002'
)

export const WechatAccountError = createErrorClass(
  'WechatAccountError',
  WechatError,
  '微信号帐号错误',
  '7003'
)

export const errorMap = new Map(Object.entries({
  1111: ServerError,
  3333: InvalidParamsError,
  5000: TokenInvalidError,
  5001: PermissionDeniedError,
  5002: RoleNameDuplicatedError,
  5003: RoleInUseError,
  5004: AdminLockedError,
  5005: ModuleNameDuplicatedError,
  5006: LoginError,
  5011: PermissionNot,
  5007: AccountNameDuplicatedError,
  6001: SignatureError,
  7001: WechatRequestError,
  7002: WechatAccountDuplicatedError,
  7003: WechatAccountError
}))

export function processError (callback) {
  const fn = this
  return async function (...args) {
    try {
      // await this::fn(...args) // => fn.call(this, ...args)
      await fn.call(this, ...args)
    } catch (e) {
      if (e instanceof RequestError) {
        // this::callback(e)
        callback.call(this, e)
      } else {
        throw e
      }
    }
  }
}

export function toastError () {
  /* return this::processError(
    // error => toast({type: 'error', title: error.message})
    error => app.$notify({type: 'error', message: error.message})
  )
  */
  return processError.call(this,
    // error => toast({type: 'error', title: error.message})
    error => app.$notify({type: 'error', message: error.message})
  )
}
